from django.shortcuts import render, redirect
from django.views import View
from django.conf import settings
from django import http
from django.contrib.auth import login
from django_redis import get_redis_connection

import logging, re

from QQLoginTool.QQtool import OAuthQQ
from meiduo_mall.utils.response_code import RETCODE
from oauth.models import OAuthQQUser
from oauth.utils import generate_access_token, check_access_token
from users.models import User
# Create your views here.


# 创建日志输出器
logger = logging.getLogger('django')


class QQAuthUserView(View):
    """用户扫码后登录的回调处理"""

    def get(self, request):
        # 提取code请求参数
        code = request.GET.get('code')
        if not code:
            return http.HttpResponseForbidden('缺少code')

        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        try:
            # 使用code向qq服务器请求access_token
            access_token = oauth.get_access_token(code)

            # 使用access_token向qq服务器请求openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('Oauth2.0 认证失败')

        # 使用openid判断该qq用户是否绑定过商城
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 没有绑定
            access_token_openid = generate_access_token(openid)
            context = {'access_token_openid': access_token_openid}
            return render(request, 'oauth_callback.html', context)
        else:
            # openid已经绑定商城：orath_user.user表示从qq登录模型类对象中找到对应的用户模型类对象
            login(request, oauth_user.user)

            # 重定向到state：从哪来，QQ登录完之后回哪去
            next = request.GET.get('state')
            response = redirect(next)

            # 将用户名写入到cookies当中
            response.set_cookie('username', oauth_user.user.username, max_age=3600 * 24 * 15)

            # 响应qq登录结果
            return response

    def post(self, request):
        """商城用户绑定openid"""
        # 接收参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        access_token_openid = request.POST.get('access_token_openid')

        # 判断参数是否齐全：all([列表]):会去校验列表中的元素是否为空，只要一个为空就返回false
        if not all([mobile, password, sms_code_client]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号码')
        # 判断密码是否是8-20个字符
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20个字符的密码')

        # 创建redis的连接对象
        redis_conn = get_redis_connection('verify_code')
        # 提取短信验证码
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})

        # 删除图形验证码
        redis_conn.delete('sms_%s' % mobile)

        # 对比
        if sms_code_client != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入的验证码有误'})

        # 判断openid是否有效：错误提斯放在openid_errmsg位置
        openid = check_access_token(access_token_openid)
        if not openid:
            return render(request, 'oauth_callback.html', {'openid_errmsg': '无效的openid'})

        # 使用手机号查询对于的用户是否存在
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果手机号不存在，新建用户
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            # 如果手机号用户存在，需要验证密码
            if not user.check_password(password):
                return render(request, 'oauth_callback.html', {'openid_errmsg': '账号或密码错误'})

        # 将用户进行绑定
        try:
            oauth_qq_user = OAuthQQUser.objects.create(user=user, openid=openid)
        except Exception as e:
            logger.error(e)
            return render(request, 'oauth_callback.html', {'qq_login_errmsg': '账号或密码错误'})

        # 状态保持
        login(request, oauth_qq_user.user)

        # 重定向到state：从哪来，QQ登录完之后回哪去
        next = request.GET.get('state')
        response = redirect(next)

        # 将用户名写入到cookies当中
        response.set_cookie('username', oauth_qq_user.user.username, max_age=3600 * 24 * 15)

        # 响应qq登录结果
        return response


class QQAuthURLView(View):
    """提供qq登录页面网址"""

    def get(self, request):
        # next 表示从哪个页面进入到的登录页面，将来登录的之后，就自动跳转到那个页面
        next = request.GET.get('next')

        # 初始化一个qq登录工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI, state=next)

        # 获取qq登录页面网址
        login_url = oauth.get_qq_url()

        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})
